/*
 *      AgendaView.java
 *      
 *      Copyright 2011 Jean Clément Nigues <jeanclement@P5E3deluxe>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 *      
 *      
 */
package pda.agenda.ihm;

import pda.agenda.controller.*;

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

import java.util.Calendar;
import java.util.GregorianCalendar;

public class AgendaView {

	// Les fenêtres
	private CardLayout fenetres;
	private JPanel lesPanel;

	// La fenêtre principale (Mois/Semaines/Jours...)
	public final static String NOM_FENETRE_PRINCIPALE = "Fenetre Principale";
	private JPanel fenetrePrincipale;
	private JTabbedPane ongletsFenetrePrincipale;
	
	// -- Onglet "Mois"
	private final static String NOM_FENETRE_MOIS = "Mois";
	private AgendaViewMois fenetreMois;

	// -- Onglet "Semaine"
	private final static String NOM_FENETRE_SEMAINE = "Semaine";
	private AgendaViewSemaine fenetreSemaine;

	// -- Onglet "Jour"
	private final static String NOM_FENETRE_JOUR = "Jour";
	private AgendaViewJour fenetreJour;

	// -- Onglet "Liste"
	private final static String NOM_FENETRE_LISTE = "Liste";
	private AgendaViewListe fenetreListe;

	// La fenêtre qui affiche les informations d'une activité
	public final static String NOM_FENETRE_INFORMATION_ACT = "Information Activite";
	private InformationActivite fenetreInfoActivite;

	// La fenêtre qui affiche le formulaire pour ajouter ou éditer une activité
	public final static String NOM_FENETRE_AJOUTER_ACTIVITE = "Ajouter ou Editer une activite";

	// La fenêtre qui affiche un message d'erreur
	public final static String NOM_FENETRE_MESSAGE_ERREUR = "Message d'erreur";
	private ViewMessageErreur fenetreMessageErreur;

	// La fenêtre qui affiche un message de confirmation
	public final static String NOM_FENETRE_MESSAGE_CONFIRMATION = "Message de confirmation";
	//private ViewMessageConfirmation fenetreMessageConfirmation;

	/**
	 * Constructeur
	 */
	public AgendaView() {
		this.creerInterface();
		this.attacherReaction();
	}

	/**
	 * Génère la liste des jours d'un mois.
	 * @param mois Le mois pour lequel on souhaite afficher les jours.
	 * @param annee L'année pour laquelle on souhaite afficher les jours, utile pour le mois de février.
	 */
	public void creerListeJoursDuMois(int mois, int annee) {
		// Indique le mois courant
		this.fenetreMois.getLabelMoisCourant().setText(this.getMois(mois));
		this.fenetreMois.getLabelAnneeCourante().setText(""+annee);

		int jour = 0;
		GregorianCalendar calendrier = new GregorianCalendar();
		// Nombre de jour, du mois précédant
		int moisPrecedant;
		int anneePrecedante;
		if(mois-1 < 0) {
			moisPrecedant = 11;
			anneePrecedante = annee-1;
		} else {
			moisPrecedant = mois-1;
			anneePrecedante = annee;
		}
		calendrier.set(Calendar.MONTH, moisPrecedant);
		calendrier.set(Calendar.YEAR, anneePrecedante);
		int nombreJourPrecedant = calendrier.getActualMaximum(Calendar.DATE);
		// Revient au mois suivant
		calendrier.set(Calendar.DAY_OF_MONTH,1);
		calendrier.set(Calendar.MONTH, mois);
		calendrier.set(Calendar.YEAR, annee);
		// Le premier jour du mois est...
		int premierJour = (calendrier.get(Calendar.DAY_OF_WEEK)-1);
		// Si c'est un dimanche, on le remet en fin de semaine.
		premierJour = (premierJour == 0) ? 7 : premierJour;
		// Les 6 premières valeurs sont reservé aux jours "Lundi", "Mardi"...
		int i = 7;
		int decalage = 6;
		for(i=7;i<(7*7);i++) {
			// Si le nombre de jour est supérieur au dernier du mois.
			if((i-decalage) > calendrier.getActualMaximum(Calendar.DATE)) {	
				this.fenetreMois.getJoursDuMois(i).setText(""+(i-decalage-calendrier.getActualMaximum(Calendar.DATE)));
				this.fenetreMois.getJoursDuMois(i).setForeground(Color.GRAY);
			// Si nous sommes pas encore au premier jours du mois
			// (Exemple, le 1er juin 2011, c'est un Mercredi
			} else if((i-6) < premierJour) {
				this.fenetreMois.getJoursDuMois(i).setText(""+((nombreJourPrecedant-premierJour+1)+(i-6)));
				this.fenetreMois.getJoursDuMois(i).setForeground(Color.GRAY);
				decalage++;
			} else {
				this.fenetreMois.getJoursDuMois(i).setText(""+(i-decalage));
				this.fenetreMois.getJoursDuMois(i).setForeground(Color.WHITE);
			}
		}
	}

	/**
	 * Génère la liste des jours d'une semaine.
	 * @param semaine Le numéro de la semaine dans l'année.
	 * @param annee L'année pour laquelle on souhaite afficher les jours, utile pour le mois de février.
	 */
	public void creerListeJoursDuneSemaine(int semaine, int annee) {

		// On recupère le mois où se situe cette semaine
		GregorianCalendar calendrier = new GregorianCalendar();
		calendrier.set(Calendar.WEEK_OF_YEAR, semaine);
		calendrier.set(Calendar.YEAR, annee);

		String suffix;
		if(semaine == 1) {
			suffix = "er";
		} else {
			suffix = "ème";
		}

		this.fenetreSemaine.getLabelSemaineCourante().setText(semaine+""+suffix+" semaine - "+this.getMois(calendrier.get(Calendar.MONTH))+" "+annee);	
	}

	/**
	 * Change le jour dans l'onglet "Jour"
	 * @param jour Le nouveau numéro du jour de l'année
	 * @param annee La nouvelle année
	 */
	public void changerJour(int jour, int annee) {
		GregorianCalendar calendrier = new GregorianCalendar();
		calendrier.set(Calendar.DAY_OF_YEAR,jour);
		calendrier.set(Calendar.YEAR,annee);
		this.fenetreJour.getLabelJourCourant().setText(this.getJour(calendrier.get(Calendar.DAY_OF_WEEK)-1)+" "+calendrier.get(Calendar.DAY_OF_MONTH)+"/"+(calendrier.get(Calendar.MONTH)+1)+"/"+calendrier.get(Calendar.YEAR));
	}

	/**
	 * Change de fenêtre 
	 * @param jour Le nouveau numéro du jour de l'année
	 * @param annee La nouvelle année
	 */
	public void changePanel(String name){
		fenetres.show(lesPanel, name);
	}

	/**
	 * Renvoi la fenêtre principale de l'application.
	 * @return la référence sur la fenêtre principale
	 */
	public JPanel getPanel() {
		return this.lesPanel;
	}

	public JTabbedPane getTabbedPane() {
		return this.ongletsFenetrePrincipale;
	}

	public AgendaViewMois getAgendaViewMois() {
		return this.fenetreMois;
	}

	public AgendaViewJour getAgendaViewJour() {
		return this.fenetreJour;
	}

	public AgendaViewSemaine getAgendaViewSemaine() {
		return this.fenetreSemaine;
	}

	public AgendaViewListe getAgendaViewListe() {
		return this.fenetreListe;
	}

	public InformationActivite getInformationActiviteView() {
		return this.fenetreInfoActivite;
	}

	public int getNumeroMois(String leMois) {
		leMois = leMois.toLowerCase();
		if(leMois.equals("janvier")) {
			return 0;
		} else if(leMois.equals("février")) {
			return 1;
		} else if(leMois.equals("mars")) {
			return 2;
		} else if(leMois.equals("avril")) {
			return 3;
		} else if(leMois.equals("mai")) {
			return 4;
		} else if(leMois.equals("juin")) {
			return 5;
		} else if(leMois.equals("juillet")) {
			return 6;
		} else if(leMois.equals("août")) {
			return 7;
		} else if(leMois.equals("septembre")) {
			return 8;
		} else if(leMois.equals("octobre")) {
			return 9;
		} else if(leMois.equals("novembre")) {
			return 10;
		} else if(leMois.equals("décembre")) {
			return 11;
		} else {
			return -1;
		}
	}

	/**
	 * Créer et place les composants sur l'interface
	 */
	private void creerInterface() {
		// Modèle qui englobe toutes les fenêtres ("principale", "message d'erreur", "message de confirmation" "ajouter une activité"....)
		this.lesPanel = new JPanel();
		this.fenetres = new CardLayout();
		this.lesPanel.setLayout(this.fenetres);
		
		// Recupère la date d'aujourd'hui
		GregorianCalendar calendrier = new GregorianCalendar();

		// Fenêtre "principale" qui affiche les onglets Mois/Semaines/Jours...
		this.fenetrePrincipale = new JPanel();
		this.ongletsFenetrePrincipale = new JTabbedPane();

		// Mise en forme des onglets
		

		// -- Onglet "Mois" de la fenêtre "principale"
		this.fenetreMois = new AgendaViewMois();
		this.creerListeJoursDuMois((calendrier.get(Calendar.MONTH)),calendrier.get(Calendar.YEAR));		
		this.ongletsFenetrePrincipale.addTab("Mois",fenetreMois);

		// -- Onglet "Semaine" de la fenêtre "principale"
		this.fenetreSemaine = new AgendaViewSemaine();
		this.creerListeJoursDuneSemaine(calendrier.get(Calendar.WEEK_OF_YEAR),calendrier.get(Calendar.YEAR));
		this.ongletsFenetrePrincipale.addTab("Semaine",fenetreSemaine);

		// -- Onglet "Jour" de la fenêtre "principale"
		this.fenetreJour = new AgendaViewJour();
		this.changerJour(calendrier.get(Calendar.DAY_OF_YEAR),calendrier.get(Calendar.YEAR));
		this.ongletsFenetrePrincipale.addTab("Jour",fenetreJour);

		// -- Onglet "Liste" de la fenêtre "principale"
		this.fenetreListe = new AgendaViewListe();
		this.ongletsFenetrePrincipale.addTab("Liste",fenetreListe);

		fenetrePrincipale.add(ongletsFenetrePrincipale);

		lesPanel.add(ongletsFenetrePrincipale,NOM_FENETRE_PRINCIPALE);

		// Fenêtre qui affiche les détails d'une Activité
		this.fenetreInfoActivite = new InformationActivite();

		lesPanel.add(fenetreInfoActivite, NOM_FENETRE_INFORMATION_ACT);
	}

	/**
	 * Ajoute les reactions aux composants de l'application.
	 */
	private void attacherReaction() {
		// Ecouteur sur les onglets
		EcouteurChangeOnglet ecouteurOnglet = new EcouteurChangeOnglet();
		this.ongletsFenetrePrincipale.addChangeListener(ecouteurOnglet);
	}

	/**
	 * Recupère le nom du mois en français
	 * @param leMois numéro du mois compris entre 0 et 11
	 * @return le nom du mois en français
	 */
	private String getMois(int leMois) {
		String[] mois = new String[12];
		mois[0] = "Janvier";
		mois[1] = "Février";
		mois[2] = "Mars";
		mois[3] = "Avril";
		mois[4] = "Mai";
		mois[5] = "Juin";
		mois[6] = "Juillet";
		mois[7] = "Août";
		mois[8] = "Septembre";
		mois[9] = "Octobre";
		mois[10] = "Novembre";
		mois[11] = "Décembre";
		return mois[leMois];
	}

	/**
	 * Recupère le nom du jour en français
	 * @param leJour numéro du jour compris entre 0 et 6
	 * @return le nom du jour en français
	 */
	private String getJour(int leJour) {
		String[] jours = new String[7];
		jours[0] = "Dimanche";
		jours[1] = "Lundi";
		jours[2] = "Mardi";
		jours[3] = "Mercredi";
		jours[4] = "Jeudi";
		jours[5] = "Vendredi";
		jours[6] = "Samedi";
		return jours[leJour];
	}
} // fin de la classe
